package com.zb.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.zb.constant.RedisConstant;
import com.zb.entity.NetworkInviteCodeVo;
import com.zb.enums.SmsType;
import com.zb.exception.SMSException;
import com.zb.util.SmsSendUtil;
import com.zb.utils.RandomUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @Author WEN
 * @Date 2024/3/19 0019
 **/
@Service
public class SmsVerificCodeService {
    /**
     * 验证码有效期（单位：秒）
     */
    private static final long EXPIRE_TIME = 5 * 60L;
    public static SmsVerificCodeService smsVerificCodeService;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @PostConstruct
    public void init() {
        smsVerificCodeService = this;
    }

    /**
     * 发送验证码
     * @param cacheRedisKey redis缓存值
     * @param phone 手机号
     * @throws SMSException
     */
    public static void sendVerificCode(String cacheRedisKey, String phone) throws SMSException {
        String code = RandomUtil.randomNumber6();
        // 发送验证码
        SmsSendUtil.sendVerifiCode(phone, code);
        // 缓存验证码
        String key = cacheRedisKey + phone;
        smsVerificCodeService.redisTemplate.opsForValue().set(key, code, EXPIRE_TIME, TimeUnit.SECONDS);
    }

    /**
     * 校验注册验证码
     * @param cacheRedisKey redis缓存值
     * @param phone 手机号
     * @param code 验证码
     * @throws SMSException
     */
    public static void checkVerificCode(String cacheRedisKey, String phone, String code) throws SMSException {
        if (StringUtils.isBlank(code)) {
            throw new SMSException("请输入校验码！");
        }
        String key = cacheRedisKey + phone;
        String o = smsVerificCodeService.redisTemplate.opsForValue().get(key);
        if (StringUtils.isBlank(o)) {
            throw new SMSException("校验码已过期！");
        }
        if (!Objects.equals(o, code)) {
            throw new SMSException("校验码输入错误！");
        }
        // 校验通过后删除验证码
        smsVerificCodeService.redisTemplate.delete(key);
    }

    /**
     * 生成并获取加入服务商的邀请码
     * @param custAccId 商家ID
     * @param networkId 服务商ID
     * @param phone 手机号，非必传
     * @return
     */
    public static String generatorJoinNetworkInviteCode(Long custAccId, Long networkId, String phone) {
        String inviteCode = RandomUtil.randomStr8();
        if (StringUtils.isNotBlank(phone)) {
            smsVerificCodeService.redisTemplate.opsForValue().set(RedisConstant.NETWORK_INVITE_CODE + phone, inviteCode,
                    RedisConstant.NETWORK_INVITE_CODE_EXPIRE_TIME, TimeUnit.SECONDS);
        }
        smsVerificCodeService.redisTemplate.opsForValue().set(
                RedisConstant.NETWORK_INVITE_CODE + inviteCode,
                JSONObject.toJSONString(new NetworkInviteCodeVo(custAccId, networkId)),
                RedisConstant.NETWORK_INVITE_CODE_EXPIRE_TIME,
                TimeUnit.SECONDS
        );
        return inviteCode;
    }

    /**
     * 校验加入服务服务商的邀请码
     * @param inviteCode 邀请码
     * @param phone 手机号
     * @throws SMSException
     */
    public static NetworkInviteCodeVo checkJoinNetworkInviteCode(String inviteCode, String phone) throws SMSException {
        if (StringUtils.isBlank(inviteCode)) {
            throw new SMSException("请输入邀请码！");
        }
        if (StringUtils.isNotBlank(phone)) {
            String phoneInviteCode = smsVerificCodeService.redisTemplate.opsForValue().get(RedisConstant.NETWORK_INVITE_CODE + phone);
            if (StringUtils.isNotBlank(phoneInviteCode)){
                if (!Objects.equals(phoneInviteCode, inviteCode)) {
                    throw new SMSException("邀请码错误");
                }
            }
        }
        String o = smsVerificCodeService.redisTemplate.opsForValue().get(RedisConstant.NETWORK_INVITE_CODE + inviteCode);
        if (StringUtils.isBlank(o)) {
            throw new SMSException("邀请码已失效");
        }
        return JSONObject.parseObject(o, NetworkInviteCodeVo.class);
    }

    /**
     * 删除短信邀请码
     * @param inviteCode 邀请码
     * @param phone 手机号
     */
    public static void deleteJoinNetworkInviteCode(String inviteCode, String phone) {
        // 仅删除以短信发送的邀请码，直接发送的等七天有效期自动过期
        smsVerificCodeService.redisTemplate.delete(phone);
    }


    /**
     * 生成邀请码并缓存
     * @param custAccId 商家ID
     * @param networkId 服务商ID
     * @param timeout 过期时间，单位秒
     * @return
     */
    public static String generateInviteCode(Long custAccId, Long networkId, Long timeout) {
        String inviteCode = RandomUtil.randomStr8();
        smsVerificCodeService.redisTemplate.opsForValue().set(RedisConstant.NETWORK_INVITE_CODE + inviteCode,
                JSONObject.toJSONString(new NetworkInviteCodeVo(custAccId, networkId)),
                null == timeout || 0 == timeout? RedisConstant.NETWORK_INVITE_CODE_EXPIRE_TIME : timeout,
                TimeUnit.SECONDS
        );
        return inviteCode;
    }

    /**
     * 清除的邀请码
     * @param inviteCode
     */
    public static void deleteInviteCode(String inviteCode) {
        smsVerificCodeService.redisTemplate.delete(RedisConstant.NETWORK_INVITE_CODE + inviteCode);
    }

    /**
     * 发送短信邀请码
     * @param custAccId 商家ID
     * @param networkId 服务商ID
     * @param phone 接收邀请码的手机号
     * @throws SMSException
     */
    public static void sendInviteCode(Long custAccId, Long networkId, String phone) throws SMSException {
        // 生成邀请码
//        String inviteCode = generateInviteCode(custAccId, networkId);
        // 发送验证码
//        SmsSendUtil.sendVerifiCode(phone, inviteCode);
    }

    /**
     * 校验邀请码
     * @param inviteCode 邀请码
     * @throws SMSException
     */
    public static NetworkInviteCodeVo checkInviteCode(String inviteCode) throws SMSException {
        if (StringUtils.isBlank(inviteCode)) {
            throw new SMSException("请输入邀请码！");
        }
        String o = smsVerificCodeService.redisTemplate.opsForValue().get(RedisConstant.NETWORK_INVITE_CODE + inviteCode);
        if (StringUtils.isBlank(o)) {
            throw new SMSException("邀请码错误或已过期！请重新获取");
        }
        return JSONObject.parseObject(o, NetworkInviteCodeVo.class);
    }

    /**
     * 获取核销码
     * @param phone 手机号
     * @param code 核销码，如果传空值则自动生成
     */
    public static void getWriteOffCode(String phone, String code) {
        String key = SmsType.WRITE_OFF_CODE.getType() + phone;
        // 缓存核销码
        smsVerificCodeService.redisTemplate.opsForValue().set(key, code, EXPIRE_TIME, TimeUnit.SECONDS);
    }

    /**
     * 核验核销码
     * @param phone 手机号
     * @param code 核销码
     */
    public static void checkWriteOffCode(String phone, String code) throws SMSException {
        checkVerificCode(SmsType.WRITE_OFF_CODE.getType(), phone, code);
    }


}
